package org.meetunexpectedly.service.middleground.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.meetunexpectedly.authority.AuthorityUtils;
import org.meetunexpectedly.entity.middleground.*;
import org.meetunexpectedly.mapper.middleground.PermissionMapper;
import org.meetunexpectedly.service.middleground.PermissionService;
import org.meetunexpectedly.service.middleground.RolePermissionService;
import org.meetunexpectedly.service.middleground.UserRoleService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 权限服务实现类
 * @Author: pupil
 * @Date: 2024/09/03 下午 8:34
 */
@Service
public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permission> implements PermissionService {

    @Autowired
    private UserRoleService userRoleService;

    @Resource
    private RolePermissionService rolePermissionService;

    // Permission比较器  用于排序
    private class PermissionComparator implements Comparator<Permission> {

        @Override
        public int compare(Permission o1, Permission o2) {
            return o1.getSort() - o2.getSort();
        }
    }

    @Override
    public Map<String, Object> initMenu(Long userId) {

        // 创建返回结果map
        Map<String, Object> data = new HashMap<>();
        List<Menu> menus = new ArrayList<>();
        List<Menu> parentMenu = new ArrayList<>();

        // 封装权限集合
        Set<String> permissionSet = new HashSet<>();

        // 根据用户id查询对应的角色id
        List<Long> roleIds = userRoleService.list(new LambdaQueryWrapper<UserRole>().eq(UserRole::getUserId, userId).select(UserRole::getRoleId))
                .stream().map(UserRole::getRoleId).collect(Collectors.toList());

        if (ObjectUtils.isEmpty(roleIds)) {
            return Collections.EMPTY_MAP;
        }

        // 根据角色id查询权限id
        List<Integer> permissionIds = rolePermissionService.list(new LambdaQueryWrapper<RolePermission>().in(RolePermission::getRoleId, roleIds).select(RolePermission::getPermissionId))
                .stream().map(RolePermission::getPermissionId).collect(Collectors.toList());

        // 根据权限id查出权限
        // 查出所有权限-->转换成对应的菜单对象
        this.list(new LambdaQueryWrapper<Permission>().in(Permission::getId, permissionIds))
                .stream()
                .sorted(new PermissionComparator())
                .forEach(permission -> {
                    Menu menu = new Menu();
                    BeanUtils.copyProperties(permission, menu);
                    menu.setTitle(permission.getName());
                    menus.add(menu);
                });


        // list转树形结构
        // 1. 先找到根节点
        for (Menu menu : menus) {
            // 校验是根节点以及根节点不为按钮的节点
            if (menu.getPId().compareTo(0L) == 0 && menu.getIsMenu() != 1) {
                parentMenu.add(menu);
            }
        }

        // 根据根节点找到子节点
        for (Menu menu : parentMenu) {
            findChild(menu, menus, permissionSet);
        }


        // 保存用户权限
        AuthorityUtils.setAuthority(userId, permissionSet);

        // 创建主页菜单
        MenuVO homeInfo = new MenuVO();
        // 创建登录菜单
        MenuVO logoInfo = new MenuVO();
        homeInfo.setTitle("首页");
        homeInfo.setHref("page/welcome.html?t=1");
        logoInfo.setTitle("邂逅管理后台");
        logoInfo.setImage("/favicon.ico");
        logoInfo.setHref("/index.html");
        data.put("menuInfo", parentMenu);
        data.put("homeInfo", homeInfo);
        data.put("logoInfo", logoInfo);

        return data;
    }

    @Override
    public List<Permission> treeSelect() {
        // 创建返回结果
        List<Permission> data = new ArrayList<>();

        // 查出所有权限（类型：按钮）
        List<Permission> permissions = this.list(new LambdaQueryWrapper<Permission>().ne(Permission::getIsMenu, 1));

        // 找到根节点
        for (Permission permission : permissions) {
            if (permission.getPId().compareTo(0L) == 0) {
                data.add(permission);
            }
        }

        // 根据根节点找到子节点
        for (Permission permission : data) {
            findTreeSelectChildren(permission, permissions);
        }

        return data;
    }

    @Override
    @Transactional
    public Boolean removePermission(Long id) {
        // 封装id集合
        List<Long> ids = new ArrayList<>();
        // 查找子权限id
        findPermissionId(id, ids);
        ids.add(id);

        try {
            // 删除权限表
            this.removeByIds(ids);
            // 删除角色权限中间表
            rolePermissionService.remove(new LambdaQueryWrapper<RolePermission>().in(RolePermission::getPermissionId, ids));
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }

        return true;

    }

    /**
     * 根据权限id查找子权限id
     *
     * @param id
     * @param ids
     */
    private void findPermissionId(Long id, List<Long> ids) {
        this.list(new LambdaQueryWrapper<Permission>().eq(Permission::getPId, id).select(Permission::getId))
                .stream()
                .forEach(permission -> {
                    ids.add(permission.getId());
                    findPermissionId(permission.getId(), ids);
                });
    }


    /**
     * 获取子权限
     *
     * @param permission  权限
     * @param permissions 权限集合
     * @return
     */
    private Permission findTreeSelectChildren(Permission permission, List<Permission> permissions) {
        permission.setChildren(new ArrayList<Permission>());

        for (Permission datum : permissions) {
            if (permission.getId().compareTo(datum.getPId()) == 0) {
                permission.getChildren().add(findTreeSelectChildren(datum, permissions));
            }
        }

        return permission;
    }


    /**
     * 获取子菜单
     *
     * @param menu          菜单
     * @param menus         菜单集合
     * @param permissionSet 权限集合
     * @return
     */
    private Menu findChild(Menu menu, List<Menu> menus, Set<String> permissionSet) {
        menu.setChild(new ArrayList<Menu>());
        for (Menu m : menus) {
            if (!ObjectUtils.isEmpty(m.getPath())) {
                permissionSet.add(m.getPath());
            }
            if (m.getIsMenu() != 1) {
                if (menu.getId().compareTo(m.getPId()) == 0) {
                    // 递归调用该方法
                    menu.getChild().add(findChild(m, menus, permissionSet));
                }
            }
        }
        return menu;
    }
}
